package com.insight.export.generator;

import com.insight.common.enums.ExportFormat;
import com.insight.entity.DataSource;
import com.insight.entity.MetadataColumn;
import com.insight.entity.MetadataIndex;
import com.insight.entity.MetadataTable;
import com.alibaba.fastjson2.JSON;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * T085: Markdown格式数据字典生成器
 * <p>
 * 生成符合CommonMark规范的Markdown格式数据字典文档.
 * 包含数据源信息、表目录、表详情(列/索引)等完整信息.
 * </p>
 *
 * <p><b>生成的文档结构</b>:</p>
 * <pre>
 * # 数据字典
 * ## 数据源信息
 * ## 表目录
 * ## 表详情
 *   ### 表1
 *   #### 列信息
 *   #### 索引信息
 *   ### 表2
 *   ...
 * </pre>
 *
 * @author Insight Team
 */
public class MarkdownExportGenerator implements ExportGenerator {

    private static final DateTimeFormatter TIMESTAMP_FORMAT =
            DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
    private static final DateTimeFormatter DISPLAY_FORMAT =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public Path generate(DataSource dataSource, List<MetadataTable> tables, Path outputDir)
            throws IOException {
        // 参数验证
        validateParameters(dataSource, tables, outputDir);

        // 确保输出目录存在
        if (!Files.exists(outputDir)) {
            Files.createDirectories(outputDir);
        }

        // 生成文件名: datasource_timestamp.md
        String timestamp = LocalDateTime.now().format(TIMESTAMP_FORMAT);
        String fileName = String.format("%s_%s.md", sanitizeFileName(dataSource.getName()), timestamp);
        Path outputFile = outputDir.resolve(fileName);

        // 生成Markdown内容
        StringBuilder markdown = new StringBuilder();
        appendHeader(markdown, dataSource);
        appendDataSourceInfo(markdown, dataSource);
        appendTableOfContents(markdown, tables);
        appendTableDetails(markdown, tables);

        // 写入文件
        Files.writeString(outputFile, markdown.toString());

        return outputFile;
    }

    @Override
    public ExportFormat getSupportedFormat() {
        return ExportFormat.MARKDOWN;
    }

    @Override
    public String getFileExtension() {
        return "md";
    }

    /**
     * 验证参数
     */
    private void validateParameters(DataSource dataSource, List<MetadataTable> tables, Path outputDir) {
        if (dataSource == null) {
            throw new IllegalArgumentException("数据源不能为null");
        }
        if (tables == null) {
            throw new IllegalArgumentException("表列表不能为null");
        }
        if (outputDir == null) {
            throw new IllegalArgumentException("输出目录不能为null");
        }
    }

    /**
     * 追加文档头部
     */
    private void appendHeader(StringBuilder sb, DataSource dataSource) {
        sb.append("# 数据字典\n\n");
        sb.append(String.format("> **数据源**: %s  \n", dataSource.getName()));
        sb.append(String.format("> **数据库类型**: %s  \n", dataSource.getDbType()));
        sb.append(String.format("> **生成时间**: %s  \n\n",
                LocalDateTime.now().format(DISPLAY_FORMAT)));
        sb.append("---\n\n");
    }

    /**
     * 追加数据源信息章节
     */
    private void appendDataSourceInfo(StringBuilder sb, DataSource dataSource) {
        sb.append("## 数据源信息\n\n");
        sb.append("| 项目 | 值 |\n");
        sb.append("|------|----|\n");
        sb.append(String.format("| 数据源名称 | %s |\n", escape(dataSource.getName())));
        sb.append(String.format("| 数据库类型 | %s |\n", dataSource.getDbType()));
        sb.append(String.format("| 主机地址 | %s:%d |\n",
                dataSource.getHost(), dataSource.getPort()));
        sb.append(String.format("| 数据库名 | %s |\n",
                dataSource.getDatabaseName() != null ? escape(dataSource.getDatabaseName()) : "N/A"));
        sb.append(String.format("| 用户名 | %s |\n", escape(dataSource.getUsername())));
        sb.append("\n");
    }

    /**
     * 追加表目录章节
     */
    private void appendTableOfContents(StringBuilder sb, List<MetadataTable> tables) {
        sb.append("## 表目录\n\n");

        if (tables.isEmpty()) {
            sb.append("*暂无表信息*\n\n");
            return;
        }

        sb.append("| 表名 | 注释 | 行数 | 数据大小 |\n");
        sb.append("|------|------|------|----------|\n");

        for (MetadataTable table : tables) {
            sb.append(String.format("| %s | %s | %,d | %s |\n",
                    escape(table.getTableName()),
                    escape(table.getTableComment() != null ? table.getTableComment() : ""),
                    table.getRowCount() != null ? table.getRowCount() : 0,
                    formatBytes(0L /* getDataLength removed */)));
        }
        sb.append("\n");
    }

    /**
     * 追加表详情章节
     */
    private void appendTableDetails(StringBuilder sb, List<MetadataTable> tables) {
        sb.append("## 表详情\n\n");

        for (MetadataTable table : tables) {
            appendTableDetail(sb, table);
        }
    }

    /**
     * 追加单个表的详细信息
     */
    private void appendTableDetail(StringBuilder sb, MetadataTable table) {
        // 表名和注释
        sb.append(String.format("### %s\n\n", escape(table.getTableName())));
        if (table.getTableComment() != null && !table.getTableComment().isEmpty()) {
            sb.append(String.format("> %s\n\n", escape(table.getTableComment())));
        }

        // 表统计信息
        sb.append("**基本信息**\n\n");
        sb.append("| 项目 | 值 |\n");
        sb.append("|------|----|\n");
        sb.append(String.format("| 模式 | %s |\n",
                escape(table.getTableSchema() != null ? table.getTableSchema() : "N/A")));
        sb.append(String.format("| 表类型 | %s |\n",
                escape(table.getTableType() != null ? table.getTableType() : "TABLE")));
        sb.append(String.format("| 行数 | %,d |\n",
                table.getRowCount() != null ? table.getRowCount() : 0));
        sb.append(String.format("| 数据大小 | %s |\n",
                formatBytes(0L /* getDataLength removed */)));
        sb.append(String.format("| 索引大小 | %s |\n",
                formatBytes(0L /* getIndexLength removed */)));
        sb.append("\n");

        // 注意: 列和索引信息需要通过Repository查询获取,当前版本暂时省略
        // TODO: 在Service层实现时,需要预加载列和索引信息

        sb.append("---\n\n");
    }


    /**
     * 格式化字节数为可读格式
     */
    private String formatBytes(Long bytes) {
        if (bytes == null || bytes == 0) {
            return "0 B";
        }
        if (bytes < 1024) {
            return bytes + " B";
        }
        if (bytes < 1024 * 1024) {
            return String.format("%.2f KB", bytes / 1024.0);
        }
        if (bytes < 1024L * 1024 * 1024) {
            return String.format("%.2f MB", bytes / (1024.0 * 1024));
        }
        return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
    }

    /**
     * 转义Markdown特殊字符
     */
    private String escape(String text) {
        if (text == null) {
            return "";
        }
        // 转义Markdown表格中的管道符
        return text.replace("|", "\\|")
                .replace("\n", " ")
                .replace("\r", "");
    }

    /**
     * 清理文件名中的非法字符
     */
    private String sanitizeFileName(String fileName) {
        if (fileName == null) {
            return "export";
        }
        // 移除Windows文件名非法字符: < > : " / \ | ? *
        return fileName.replaceAll("[<>:\"/\\\\|?*]", "_");
    }
}
